package com.lp.exception;

import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Configuration
public class GlobalExceptionConfig implements ErrorWebExceptionHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        //1.获取响应对象
        ServerHttpResponse response = exchange.getResponse();
        //2.response 如果结束，直接返回就可以
        if(response.isCommitted()) {
            return Mono.error(ex);
        }
        //3.设置响应头类型(JSON)
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        //4.设置响应状态
        if(ex instanceof TokenException) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
        } else {
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        //5.统一异常返回
        return response.writeWith(Mono.fromSupplier(() -> {
            DataBufferFactory bufferFactory = response.bufferFactory();
            return bufferFactory.wrap(result(403, ex.getMessage()));
        }));
    }

    /**
     * 封装响应结果
     * @param code
     * @param msg
     * @return
     */
    public byte[] result(Integer code, String msg) {
        Map<String, Object> errorInfo = new HashMap<>();
        errorInfo.put("code", code);
        errorInfo.put("msg", msg);
        byte[] errJson = null;
        try {
            errJson = objectMapper.writeValueAsBytes(errorInfo);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return errJson;
    }

}
